(function () {
    "use strict";

    angular.module('core').controller('_layoutController', controller);
    controller.$inject = ['$scope', '$state', '$stateParams', '$window', '$confirm', 'toastr', 'toolsService', 'configService', 'securityService', 'baseService', 'enumService'];

    function controller($scope, $state, $stateParams, $window, $confirm, toastr, toolsService, configService, securityService, baseService, enumService) {

        $scope.Title = '...';
        $scope.config = {
            data: {},
            get: async function () {
                try {
                    const response = await configService.get(true);

                    if (response.Status < 0) {
                        toastr.error(response.Message, 'Serviço');
                    }
                    else {
                        $scope.config.data = response.Data;
                    }
                } catch (err) {
                    toastr.error(err.message, "Serviço");
                } finally {

                }
            }
        };
        $scope.menu = {
            data: {},
            get: function () {
                $scope.menu.data = {
                    principais: [
                        { titulo: 'Capa', materialIcon: 'home', state: 'state-home', descricao: 'Tela principal e inicial do sistema.', allowed: true },
                    ],
                };
            }
        };
        $scope.perfil = {
            data: {},
            get: async function () {
                try {
                    const response = await securityService.getIdentityInfo();

                    if (response.Status < 0)
                        console.error('Identidade do Usuário', response.Message);
                    else
                        $scope.perfil.data = response.Data;

                } catch (err) {
                    toastr.error(err.message, 'Sem comunicação com o servidor');
                    console.error(err);
                }
            }
        };
        $scope.licenciamento = {
            enum: { expiradaOuInvalida: -2, erro: -1, ok: 1 },
            licenciar: false,
            mensagem: '',
            newLicenca: '',
            save: async function () {
                try {

                    $scope.login.carregando = true;
                    const response = await securityService.saveLicenca($scope.licenciamento.newLicenca);

                    if (response.Status < 0) {
                        console.error(response.Exception);
                    }
                    else {
                        $scope.initialize();
                    }
                } catch (err) {
                    toastr.error(err.message, 'Comunicação com o servidor.');
                    console.error(err);
                } finally {
                    $scope.login.carregando = false;
                }

            },
            check: async function () {
                try {
                    $scope.licenciamento.message = '';
                    const response = await securityService.checkLicenca();

                    if (response.Status === $scope.licenciamento.enum.expiradaOuInvalida) {
                        $scope.licenciamento.licenciar = true;
                        $scope.licenciamento.message = response.Message;
                    } else if (response.Status === $scope.licenciamento.enum.erro) {
                        $scope.licenciamento.licenciar = true;
                        toastr.error(response.Message);
                    } else {
                        $scope.licenciamento.licenciar = false;
                    }

                    if ($scope.licenciamento.licenciar)
                        await $scope.licenciamento.request();

                } catch (err) {
                    toastr.error(err.message, 'Comunicação com o servidor');
                    console.error(err);
                }
            },
            request: async function () {
                try {

                    $scope.licenciamento.requestLicenca = '';
                    const response = await securityService.requestLicenca();

                    if (response.Status < 0) {
                        toastr.error(response.Message);
                    } else
                        $scope.licenciamento.requestLicenca = response.Data;

                } catch (err) {
                    toastr.error(err.message, 'Comunicação com o servidor');
                    console.error(err);
                }
            }
        };
        $scope.modulo = {
            data: [],
            getAll: async function () {
                try {
                    const response = await configService.getAllNavegacaoModulo();

                    if (response.Status < 0)
                        toastr.error(response.Message, 'Serviço');
                    else {
                        angular.copy(angular.fromJson(response.Data), $scope.modulo.data);
                    }
                } catch (err) {
                    toastr.error(err.message, "Serviço");
                    console.error(err);
                }
            }
        };
        $scope.currentState = {
            data: {},
            permite: {},
            getRota: async () => {
                try {
                    const response = await configService.getNavegacao($state.current.name);

                    if (response.Status < 0)
                        toastr.error(response.Message, 'Serviço');
                    else
                        $scope.currentState.data = response.Data;

                } catch (err) {
                    toastr.error(err.message, "Serviço");
                    console.error(err);
                }
            },
            getPermissaoObjeto: async () => {

                try {
                    var args = { itemID: $scope.base.entity.ID };

                    const response = await securityService.getPermiteObjeto(args);

                    if (response.Status >= 0) {
                        $scope.currentState.permite = response.Data;
                    }

                } catch (error) {
                    toastr.error('Permissão');
                    console.error("catch", error);
                } 
            },
            getPermissaoRota: async () => {

                try {
                    var args = { rota: $state.current.name };

                    const response = await securityService.getPermiteRota(args);

                    if (response.Status >= 0) {
                        $scope.currentState.permite = response.Data;
                    }

                } catch (error) {
                    toastr.error('Permissão');
                    console.error("catch", error);
                } 
            },
            refresh: async () => {

                await $scope.currentState.getRota();

                if ($scope.base.entity?.ID) {
                    await $scope.currentState.getPermissaoObjeto();
                } else {
                    await $scope.currentState.getPermissaoRota();
                }
            },
        };
        $scope.sideNav = {
            ativo: false,
            toggle: function () {
                $scope.sideNav.ativo = !$scope.sideNav.ativo;
            },
        };
        $scope.login = {
            login: '',
            chaveAcesso: '',
            manterConectado: false,
            carregando: false,
            signIn: async function () {
                $('form').removeClass('shake animated');
                if (!$scope.login.login || !$scope.login.chaveAcesso)
                    return false;

                $scope.licenciamento.mensagem = '';
                $scope.login.carregando = true;

                try {
                    const response = await securityService.signIn($scope.login.login, $scope.login.chaveAcesso, $scope.login.manterConectado);

                    if (response.Status === $scope.licenciamento.enum.expiradaOuInvalida) {
                        $scope.licenciamento.licenciar = true;
                        $scope.licenciamento.mensagem = response.Message;

                    } else if (response.Status === $scope.licenciamento.enum.erro) {
                        toastr.error(response.Message, 'Login de Acesso');
                        $('form').addClass('shake animated');

                    } else { //credenciais ok
                        $scope.perfil.data = response.Data;
                        $state.go('state-home', {}, { reload: true, location: 'replace' });
                        await $scope.config.get();
                        $scope.login.chaveAcesso = '';

                        if (response.Status === $scope.licenciamento.enum.ok)
                            toastr.info(reponse.Message);
                    }
                }
                catch (err) {
                    toastr.error(err.message, 'Comunicação com o servidor.');
                    console.error(err);
                }
                finally {
                    $scope.login.carregando = false;
                }
            },
            signOut: async function () {
                try {
                    const response = await securityService.signOut();

                    toastr.info('Efetuando log-off...');
                    $scope.perfil.data = {};
                    $state.go('state-login', {}, { reload: true, location: 'replace' });
                    $scope.sideNav.ativo = false;
                    toastr.clear($(this));
                }
                catch (err) {
                    toastr.error(err.message, 'Sem comunicação com o servidor');
                    console.error(err);
                }
            }
        };

        $scope.historyBack = function () {
            $window.history.back();
        };
        $scope.cacheVersion = {
            get: function () {
                var val = parseInt(localStorage.getItem('cacheVersion'));
                if (!val) val = 0;
                return val;
            },
            setNew: function () {
                var val = $scope.cacheVersion.get() + 1;
                localStorage.setItem('cacheVersion', val);
                return val;
            }
        };
        $scope.confirm = $confirm;
        $scope.tools = toolsService;
        $scope.enum = enumService;
        $scope.message = {
            default: {
                serverNotFound: "Não foi possível conectar com o(s) servidor(es)"
            }
        };

        /*utilizado nos escopos filhos de forma genérica. */
        $scope.base = {
            entity: { ID: null },
            ativo: false,
            tabs: {
                index: 0,
                acompanhamento: {
                    data: [], carregando: false, vazio: true, index: 0,
                    refresh: async () => {
                        if (!$scope.base.entity?.ID)
                            return;
                        if ($scope.base.tabs.acompanhamento.carregando)
                            return;

                        $scope.base.tabs.acompanhamento.carregando = true;
                        try {

                            var args = { filtro: { Base: { ID: $scope.base.entity.ID } } };

                            const response = await baseService.getAllAcompanhamento(args);

                            if (response.Status < 0)
                                toastr.error(response.Message, 'Serviço');
                            else
                                angular.copy(angular.fromJson(response.Data), $scope.base.tabs.acompanhamento.data);

                            $scope.base.tabs.acompanhamento.vazio = ($scope.base.tabs.acompanhamento.data == 0);
                        } catch (err) {
                            toastr.error(_error, "Serviço");
                        } finally {
                            $scope.base.tabs.acompanhamento.carregando = false;
                        }
                    }
                },
                comentario: {
                    data: [], carregando: false, vazio: true, index: 1,
                    refresh: async () => {
                        if (!$scope.base.entity?.ID)
                            return;
                        if ($scope.base.tabs.comentario.carregando)
                            return;
                        $scope.base.tabs.comentario.carregando = true;

                        try {
                            var args = { filtro: { Base: { ID: $scope.base.entity.ID } } };

                            const response = await baseService.getAllComentario(args);

                            if (response.Status < 0)
                                toastr.error(response.Message, 'Serviço');
                            else
                                angular.copy(angular.fromJson(response.Data), $scope.base.tabs.comentario.data);

                            $scope.base.tabs.comentario.vazio = ($scope.base.tabs.comentario.data == 0);
                        } catch (err) {
                            toastr.error(_error, "Serviço");
                        } finally {
                            $scope.base.tabs.comentario.carregando = false;
                        }
                    }
                },
                anexo: {
                    data: [], carregando: false, vazio: true, index: 2,
                    refresh: async () => {
                        if (!$scope.base.entity?.ID)
                            return;
                        if ($scope.base.tabs.anexo.carregando)
                            return;
                        $scope.base.tabs.anexo.carregando = true;

                        try {
                            var args = { filtro: { Base: { ID: $scope.base.entity.ID } } };

                            const response = await baseService.getAllAnexo(args);

                            if (response.Status < 0)
                                toastr.error(response.Message, 'Serviço');
                            else
                                angular.copy(angular.fromJson(response.Data), $scope.base.tabs.anexo.data);

                            $scope.base.tabs.anexo.vazio = ($scope.base.tabs.anexo.data == 0);
                        } catch (err) {
                            toastr.error(_error, "Serviço");
                        } finally {
                            $scope.base.tabs.anexo.carregando = false;
                        }
                    }
                },
                compartilhamento: {
                    data: [], carregando: false, vazio: true, index: 3,
                    refresh: async () => {
                        if (!$scope.base.entity?.ID)
                            return;
                        if ($scope.base.tabs.compartilhamento.carregando)
                            return;
                        $scope.base.tabs.compartilhamento.carregando = true;

                        try {
                            var args = { filtro: { Base: { ID: $scope.base.entity.ID } } };

                            const response = await baseService.getAllCompartilhamento(args);

                            if (response.Status < 0)
                                toastr.error(response.Message, 'Serviço');
                            else
                                angular.copy(angular.fromJson(response.Data), $scope.base.tabs.compartilhamento.data);

                            $scope.base.tabs.compartilhamento.vazio = ($scope.base.tabs.compartilhamento.data == 0);
                        } catch (err) {
                            toastr.error(err, "Serviço");
                        } finally {
                            $scope.base.tabs.compartilhamento.carregando = false;
                        }
                    }
                },
                tag: {
                    data: [], carregando: false, vazio: true, index: 4,
                    refresh: async () => {
                        if (!$scope.base.entity?.ID)
                            return;
                        if ($scope.base.tabs.tag.carregando)
                            return;
                        $scope.base.tabs.tag.carregando = true;

                        try {
                            var args = { filtro: { Base: { ID: $scope.base.entity.ID } } };

                            const response = await baseService.getAllTag(args);

                            if (response.Status < 0) {
                                toastr.error(response.Message, 'Serviço');
                            }
                            else
                                angular.copy(angular.fromJson(response.Data), $scope.base.tabs.tag.data);

                            $scope.base.tabs.tag.vazio = !($scope.base.tabs.tag.data && $scope.base.tabs.tag.data.length > 0);
                        } catch (err) {
                            toastr.error(err.message, "Serviço");
                        } finally {
                            $scope.base.tabs.tag.carregando = false;
                        }
                    }
                },
                propriedade: {
                    carregando: false, index: 5,
                    refresh: async () => {

                        /* se já foi carregado pela tela específica */
                        if (!$scope.base.entity.Codigo)
                            return;

                        try {
                            $scope.base.tabs.propriedade.carregando = true;

                            const response = await baseService.get($scope.base.entity.ID);

                            if (response.Status < 0)
                                $scope.tools.toastr.error(response.Message);
                            else
                                $scope.base.entity = response.Data;

                        } catch (error) {
                            toastr.error(err.message, "Serviço");
                        } finally {
                            $scope.base.tabs.propriedade.carregando = false;
                        }
                    }
                },
            },
            toggle: (index) => {
                $scope.base.tabs.index = index;
                $scope.base.ativo = !$scope.base.ativo;

                if ($scope.base.ativo)
                    $scope.base.refresh(index);

                $scope.$digest;
            },
            refresh: async (index) => {
                $scope.base.tabs.index = index;
                switch ($scope.base.tabs.index) {
                    case $scope.base.tabs.acompanhamento.index:
                        await $scope.base.tabs.acompanhamento.refresh();
                        break;
                    case $scope.base.tabs.comentario.index:
                        await $scope.base.tabs.comentario.refresh();
                        break;
                    case $scope.base.tabs.anexo.index:
                        await $scope.base.tabs.anexo.refresh();
                        break;
                    case $scope.base.tabs.compartilhamento.index:
                        await $scope.base.tabs.compartilhamento.refresh();
                        break;
                    case $scope.base.tabs.tag.index:
                        await $scope.base.tabs.tag.refresh();
                        break;
                    case $scope.base.tabs.propriedade.index:
                        await $scope.base.tabs.propriedade.refresh();
                        break;
                }
                $scope.$digest();
            },
        };
        $scope.mapa = {
            ativo: false,
            url: null,
            toggle: (address) => {
                $scope.mapa.ativo = !$scope.mapa.ativo;
                if ($scope.mapa.ativo) {
                    $scope.mapa.url = $scope.tools.maps.getEmbeddedUrl(address);
                }
            },
        };
        $scope.pdf = {
            ativo: false,
            url: null,
            toggle: (url) => {
                $scope.pdf.ativo = !$scope.pdf.ativo;
                if ($scope.pdf.ativo) {
                    $scope.pdf.url = url;
                }
            }
        };
        $scope.localStorage = {
            setItem: function (key, val) {
                $window.localStorage.setItem($state.current.name + '.' + key, angular.toJson(val));
            },
            getItem: function (key) {
                return angular.fromJson($window.localStorage.getItem($state.current.name + '.' + key));
            }
        };
        $scope.sort = function (newExpression, filtro, callback) {
            if (newExpression === filtro.args.sortExpression)
                newExpression = newExpression + ' desc';

            filtro.args.sortExpression = newExpression;
            if (callback)
                callback();
        };
        $scope.notDeleted = function (item) {
            return !item.Deleted;
        };

        $scope.initializeLayout = async function (title) {
            $scope.Title = title;

            if ($stateParams.id)
                $scope.base.entity.ID = $stateParams.id;

            await $scope.currentState.refresh();

            $scope.login.carregando = false;

            window.sc = $scope;
            window.st = $state.current;
        };
        $scope.initialize = async function () {
            await $scope.config.get();
            $scope.menu.get();
            await $scope.perfil.get();
            await $scope.licenciamento.check();
            await $scope.modulo.getAll();
            await $scope.currentState.refresh();

            $scope.$digest();
        };

        $scope.initialize();
    }
})();